package com.ms.pda.utils.frid

import android.app.Activity
import android.os.AsyncTask
import android.text.TextUtils
import android.util.Log
import com.zebra.rfid.api3.ACCESS_OPERATION_CODE
import com.zebra.rfid.api3.ACCESS_OPERATION_STATUS
import com.zebra.rfid.api3.ENUM_TRANSPORT
import com.zebra.rfid.api3.ENUM_TRIGGER_MODE
import com.zebra.rfid.api3.HANDHELD_TRIGGER_EVENT_TYPE
import com.zebra.rfid.api3.InvalidUsageException
import com.zebra.rfid.api3.OperationFailureException
import com.zebra.rfid.api3.RFIDReader
import com.zebra.rfid.api3.ReaderDevice
import com.zebra.rfid.api3.Readers
import com.zebra.rfid.api3.RfidEventsListener
import com.zebra.rfid.api3.RfidReadEvents
import com.zebra.rfid.api3.RfidStatusEvents
import com.zebra.rfid.api3.START_TRIGGER_TYPE
import com.zebra.rfid.api3.STATUS_EVENT_TYPE
import com.zebra.rfid.api3.STOP_TRIGGER_TYPE
import com.zebra.rfid.api3.TriggerInfo

class Zebra123FridManager(activity: Activity, onRfidEventsListener: OnRfidEventsListener?) :
    BaseFridManager(activity, onRfidEventsListener) {
    private var readers: Readers?
    private var readerDevice: ReaderDevice? = null
    private var reader: RFIDReader? = null
    private var eventHandler: EventHandler? = null

    init {
        readers = Readers(activity.applicationContext, ENUM_TRANSPORT.SERVICE_USB)
    }

    override fun connect() {
        object : AsyncTask<Any?, Any?, Any?>() {
            override fun doInBackground(objects: Array<Any?>): Any? {
                try {
                    readers?.GetAvailableRFIDReaderList()?.let { availableRFIDReaderList ->
                        if (availableRFIDReaderList.isNotEmpty()) {
                            readerDevice = availableRFIDReaderList[0] as ReaderDevice
                            reader = readerDevice?.rfidReader
                            if (reader?.isConnected() == false) {
                                // Establish connection to the RFID Reader
                                reader?.connect()
                                setConfigureReader()
                                return true
                            }
                        }
                    }

                } catch (e: Exception) {
                    e.printStackTrace()
                    onRfidEventsListener?.onRfidFailure(e)
                }
                return false
            }
        }.execute()
    }

    override fun onDestroy() {
        try {
            activity = null
            onRfidEventsListener = null
            if (reader != null) {
                reader!!.Events.removeEventsListener(eventHandler)
                reader!!.disconnect()
                reader = null
                readers!!.Dispose()
                readers = null
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private fun setConfigureReader() {
        if (reader!!.isConnected) {
            onRfidEventsListener?.onRfidConnecting()
            val triggerInfo = TriggerInfo()
            triggerInfo.StartTrigger.triggerType = START_TRIGGER_TYPE.START_TRIGGER_TYPE_IMMEDIATE
            triggerInfo.StopTrigger.triggerType = STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_IMMEDIATE
            try {
                // receive events from reader
                if (eventHandler == null) eventHandler = EventHandler()
                reader!!.Events.addEventsListener(eventHandler)
                // HH event
                reader!!.Events.setHandheldEvent(true)
                // tag event with tag data
                reader!!.Events.setTagReadEvent(true)
                // application will collect tag using getReadTags API
                reader!!.Events.setAttachTagDataWithReadEvent(false)
                // set trigger mode as rfid so scanner beam will not come
                reader!!.Config.setTriggerMode(ENUM_TRIGGER_MODE.BARCODE_MODE, true)
                // set start and stop triggers
                reader!!.Config.startTrigger = triggerInfo.StartTrigger
                reader!!.Config.stopTrigger = triggerInfo.StopTrigger

//                TagStorageSettings tagStorageSettings = reader.Config.getTagStorageSettings();
//                TAG_FIELD[] tagField = new TAG_FIELD[4];
//                tagField[0] = TAG_FIELD.PC; tagField[1] =
//                        TAG_FIELD.PEAK_RSSI; tagField[2] =
//                        TAG_FIELD.TAG_SEEN_COUNT; tagField[3] =
//                        TAG_FIELD.CRC;
//                tagStorageSettings.setTagFields(tagField);
//                reader.Config.setTagStorageSettings(tagStorageSettings);

//                TagAccess tagAccess = new TagAccess();
//                TagAccess.ReadAccessParams readAccessParams = tagAccess.new ReadAccessParams();
//                readAccessParams.setMemoryBank(MEMORY_BANK.MEMORY_BANK_USER);
//                readAccessParams.setCount(0);
//                reader.Actions.TagAccess.readEvent(readAccessParams, null, null);
            } catch (e: Exception) {
                e.printStackTrace()
                onRfidEventsListener?.onRfidFailure(e)
            }
        }
    }

    inner class EventHandler : RfidEventsListener {
        // Read Event Notification
        override fun eventReadNotify(e: RfidReadEvents) {
            // Recommended to use new method getReadTagsEx for better performance in case of large tag population
            val myTags = reader!!.Actions.getReadTags(frequency)
            val tagIds: MutableList<String> = ArrayList()
            if (myTags != null) {
                for (myTag in myTags) {
//                    InventoryListItem inventoryListItem = new InventoryListItem();
                    val tagId = myTag.tagID
                    if (!tagIds.contains(tagId)) {
//                        Log.d(TAG, "Tag ID $tagId")
//                        Log.d(TAG, "Tag peakRSSI: ${myTag.peakRSSI}")
                        if (!TextUtils.isEmpty(tagId) && myTag.peakRSSI > signalIntensity) {
                            tagIds.add(tagId)
                        }
//                    if (myTag.opCode === ACCESS_OPERATION_CODE.ACCESS_OPERATION_READ &&
//                        myTag.opStatus === ACCESS_OPERATION_STATUS.ACCESS_SUCCESS
//                    ) {
//                        if (myTag.memoryBankData.length > 0) {
//                            Log.d(TAG, " Mem Bank Data " + myTag.memoryBankData)
//                        }
//                    }
                        //                    oldObject.setPC(Integer.toString(tagData.getPC()));
//                    oldObject.setPhase(Integer.toString(tagData.getPhase()));
//                    oldObject.setChannelIndex(Integer.toString(tagData.getChannelIndex()));
//                    if (rssi) oldObject.setRSSI(Integer.toString(tagData.getPeakRSSI()));
                    }

                }
            }
            if (tagIds.size > 0) {
                Log.d(TAG, " onRfidEventsListener onSuccess tagId:$tagIds")
                activity?.runOnUiThread {
                    onRfidEventsListener?.onRfidSuccess(tagIds)
                }
            }
        }

        // Status Event Notification
        override fun eventStatusNotify(rfidStatusEvents: RfidStatusEvents) {
            Log.d(TAG, "Status Notification: " + rfidStatusEvents.StatusEventData.statusEventType)
            if (rfidStatusEvents.StatusEventData.statusEventType === STATUS_EVENT_TYPE.HANDHELD_TRIGGER_EVENT) {
                if (rfidStatusEvents.StatusEventData.HandheldTriggerEventData.handheldEvent === HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_PRESSED) {
                    object : AsyncTask<Any?, Any?, Any?>() {
                        override fun doInBackground(objects: Array<Any?>): Any? {
                            try {
                                reader!!.Actions.Inventory.perform()
                            } catch (e: InvalidUsageException) {
                                e.printStackTrace()
                            } catch (e: OperationFailureException) {
                                e.printStackTrace()
                            }
                            return null
                        }
                    }.execute()
                } else if (rfidStatusEvents.StatusEventData.HandheldTriggerEventData.handheldEvent === HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_RELEASED) {
                    object : AsyncTask<Any?, Any?, Any?>() {
                        override fun doInBackground(objects: Array<Any?>): Any? {
                            try {
                                reader!!.Actions.Inventory.stop()
                            } catch (e: InvalidUsageException) {
                                e.printStackTrace()
                            } catch (e: OperationFailureException) {
                                e.printStackTrace()
                            }
                            return null
                        }
                    }.execute()
                } else if (rfidStatusEvents.StatusEventData.statusEventType === STATUS_EVENT_TYPE.DISCONNECTION_EVENT) {
                    onRfidEventsListener?.onRfidDisConnected()
                }
            }
        }
    }

    companion object {
        private const val TAG = "FridManager"
    }
}